package cn.ddiancan.xddcloud.psc.flow.entity;

import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

import cn.ddiancan.xddcloud.psc.flow.engine.core.FlowCreator;
import cn.ddiancan.xddcloud.psc.flow.context.XddcloudContext;
import cn.ddiancan.xddcloud.psc.flow.enums.AgentType;
import cn.ddiancan.xddcloud.psc.flow.engine.model.NodeAssignee;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

/**
 * 任务参与者实体类
 * @since 1.0
 */
@Getter
@Setter
@ToString
public class XddTaskActor implements Serializable {

    /**
     * 主键ID
     */
    protected Long id;

    /**
     * 租户ID
     */
    protected String tenantId;

    /**
     * 流程实例ID
     */
    protected Long instanceId;

    /**
     * 关联的任务ID
     */
    protected Long taskId;

    /**
     * 关联的参与者ID（参与者可以为用户、部门、角色）
     */
    protected Long actorId;

    /**
     * 关联的参与者名称
     */
    protected String actorName;

    /**
     * 参与者类型 0，用户 1，角色 2，部门
     */
    protected Integer actorType;

    /**
     * 权重
     * 票签任务时，该值为不同处理人员的分量比例

     */
    protected Integer weight;

    /**
     * 代理人ID
     */
    protected Long agentId;

    /**
     * 代理人类型 0，代理 1，被代理 2，认领角色 3，认领部门
     */
    protected Integer agentType;

    /**
     * 扩展json
     */
    protected String extend;

    /**
     * 是否为代理人
     *
     * @return true 是 false 否
     */
    public boolean agentActor() {
        return Objects.equals(0, this.actorType);
    }

    public boolean eqActorId(String actorId) {
        return Objects.equals(this.actorId, actorId);
    }

    public static XddTaskActor of(FlowCreator flowCreator, XddTask flwTask) {
        XddTaskActor flwTaskActor =
            ofUser(flowCreator.getTenantId(), flowCreator.getCreateBy(), flowCreator.getCreateName());
        flwTaskActor.setInstanceId(flwTask.getInstanceId());
        flwTaskActor.setTaskId(flwTask.getId());
        return flwTaskActor;
    }

    public static XddTaskActor ofAgentIt(FlowCreator flowCreator) {
        XddTaskActor flwTaskActor = new XddTaskActor();
        flwTaskActor.setAgentId(flowCreator.getCreateBy());
        flwTaskActor.setAgentType(1);
        Map<String, Object> map = new HashMap<>();
        map.put("createBy", flowCreator.getCreateBy());
        flwTaskActor.setExtendOf(map);
        return flwTaskActor;
    }

    public static XddTaskActor ofAgent(AgentType agentType, FlowCreator flowCreator, XddTask flwTask,
        XddTaskActor agentTaskActor) {
        XddTaskActor flwTaskActor = of(flowCreator, flwTask);
        flwTaskActor.setAgentId(agentTaskActor.getActorId());
        flwTaskActor.setAgentType(agentType.getValue());
        Map<String, Object> map = new HashMap<>();
        map.put("actorType", agentTaskActor.getActorType());
        map.put("actorName", agentTaskActor.getActorName());
        flwTaskActor.setExtendOf(map);
        return flwTaskActor;
    }

    public static XddTaskActor ofXddTask(XddTask flwTask) {
        XddTaskActor flwTaskActor =
            XddTaskActor.ofUser(flwTask.getTenantId(), flwTask.getCreateBy(), flwTask.getCreateName());
        flwTaskActor.setInstanceId(flwTask.getInstanceId());
        flwTaskActor.setTaskId(flwTask.getId());
        return flwTaskActor;
    }

    public static XddTaskActor ofFlowCreator(FlowCreator flowCreator) {
        return ofUser(flowCreator.getTenantId(), flowCreator.getCreateBy(), flowCreator.getCreateName());
    }

    public static XddTaskActor ofXddInstance(XddInstance flwInstance, Long taskId) {
        XddTaskActor flwTaskActor =
            ofUser(flwInstance.getTenantId(), flwInstance.getCreateBy(), flwInstance.getCreateName());
        flwTaskActor.setInstanceId(flwInstance.getId());
        flwTaskActor.setTaskId(taskId);
        return flwTaskActor;
    }

    public static XddTaskActor ofNodeAssignee(NodeAssignee nodeAssignee) {
        return ofUser(nodeAssignee.getTenantId(), nodeAssignee.getId(), nodeAssignee.getName());
    }

    public static XddTaskActor ofUser(String tenantId, Long actorId, String actorName) {
        return of(tenantId, actorId, actorName, 0, null);
    }

    public static XddTaskActor ofRole(String tenantId, Long actorId, String actorName) {
        return of(tenantId, actorId, actorName, 1, null);
    }

    public static XddTaskActor ofDepartment(String tenantId, Long actorId, String actorName) {
        return of(tenantId, actorId, actorName, 2, null);
    }

    public static XddTaskActor of(NodeAssignee nodeAssignee, Integer actorType) {
        return of(nodeAssignee.getTenantId(), nodeAssignee.getId(), nodeAssignee.getName(), actorType,
            nodeAssignee.getWeight());
    }

    public static XddTaskActor of(Long taskId, XddHisTaskActor t) {
        XddTaskActor flwTaskActor =
            of(t.getTenantId(), t.getActorId(), t.getActorName(), t.getActorType(), t.getWeight());
        flwTaskActor.setTaskId(taskId);
        flwTaskActor.setInstanceId(t.getInstanceId());
        return flwTaskActor;
    }

    protected static XddTaskActor of(String tenantId, Long actorId, String actorName, Integer actorType,
        Integer weight) {
        XddTaskActor taskActor = new XddTaskActor();
        taskActor.setTenantId(tenantId);
        taskActor.setActorId(actorId);
        taskActor.setActorName(actorName);
        taskActor.setActorType(actorType);
        taskActor.setWeight(weight);
        return taskActor;
    }

    public static XddTaskActor ofXddHisTaskActor(Long taskId, XddHisTaskActor hta) {
        XddTaskActor taskActor = new XddTaskActor();
        taskActor.setTenantId(hta.getTenantId());
        taskActor.setInstanceId(hta.getInstanceId());
        taskActor.setTaskId(taskId);
        taskActor.setActorId(hta.getActorId());
        taskActor.setActorName(hta.getActorName());
        taskActor.setActorType(hta.getActorType());
        taskActor.setWeight(hta.getWeight());
        taskActor.setAgentId(hta.getAgentId());
        taskActor.setAgentType(hta.getAgentType());
        taskActor.setExtend(hta.getExtend());
        return taskActor;
    }

    public void setExtendOf(Object object) {
        this.extend = XddcloudContext.toJson(object);
    }
}
